#include "osal.h"

#ifdef __tds__
typedef struct {
	ID task_id;
	int is_task_running;
	MUTEX mutex;
	COND cond;
	THREAD_ENTRY entry;
} TDS_TASK_PARAM;

static void tds_task_entry(DWORD param1, DWORD param2)
{
	TDS_TASK_PARAM *task_param = (TDS_TASK_PARAM *)param1;

	task_param->entry(param2);
	
	MutexLock(&task_param->mutex);
	task_param->is_task_running = 0;
	CondNotify(&task_param->cond);
	MutexUnlock(&task_param->mutex);
}
#endif

THREAD thread_create_joinable(THREAD_ENTRY entry, void *param)
{
#ifdef __tds__
   	T_CTHD t_cthd;
	TDS_TASK_PARAM *task_param = NULL;

	task_param = (TDS_TASK_PARAM *)malloc(sizeof (TDS_TASK_PARAM));
	if (NULL == task_param) {
		return NULL;
	}

	MutexInit(&task_param->mutex);
	//CondInit(&task_param->cond);
	task_param->is_task_running = 1;
	task_param->entry = entry;

	t_cthd.task = tds_task_entry;
	t_cthd.stksz = 1024 * 1024;
	t_cthd.quantum = 10;
	t_cthd.itskpri = OSAL_PRI_NORMAL;;
	t_cthd.name[0]='O';
	t_cthd.name[1]='S';
	t_cthd.name[2]='A';
	t_cthd.para1 = task_param;
	t_cthd.para2 = param;
	
	task_param->task_id = osal_task_create(&t_cthd);
	if (OSAL_INVALID_ID == task_param->task_id) {
		MutexDestroy(&task_param->mutex);
		CondDestroy(&task_param->cond);
		free(task_param);
		return NULL;
	}

	return (void *)task_param;
#else
	pthread_t threadId;

	if (0 != pthread_create(&threadId, NULL, entry, param)) {
		return NULL_THREAD;
	}
	return threadId;
#endif
}

void thread_join(THREAD thread)
{
	if (NULL_THREAD == thread) {
		return;
	}

#ifdef __tds__
	TDS_TASK_PARAM *task_param = (TDS_TASK_PARAM *)thread;
	
	/*MutexLock(&task_param->mutex);
    
	while (task_param->is_task_running) {
		CondWait(&task_param->cond, &task_param->mutex);
	}
	MutexUnlock(&task_param->mutex);
*/	
	MutexDestroy(&task_param->mutex);
	//CondDestroy(&task_param->cond);
	free(task_param);

	//osal_task_delete(thread);
#else
	pthread_join(thread, NULL);
#endif
}

void MutexInit(MUTEX *mutex)
{
#ifdef __tds__
	*mutex = osal_mutex_create();
#else
	pthread_mutex_init(mutex, NULL);
#endif
}

void MutexLock(MUTEX *mutex)
{
#ifdef __tds__
	osal_mutex_lock(*mutex, TMO_FEVR);
#else
	pthread_mutex_lock(mutex);
#endif
}

void MutexUnlock(MUTEX *mutex)
{
#ifdef __tds__
	osal_mutex_unlock(*mutex);
#else
	pthread_mutex_unlock(mutex);
#endif
}

void MutexDestroy(MUTEX *mutex)
{
#ifdef __tds__
	osal_mutex_delete(*mutex);
#else
	pthread_mutex_destroy(mutex);
#endif
}

void CondInit(COND *cond)
{
#ifdef __tds__
	*cond = osal_flag_create(0);
#else
	pthread_cond_init(cond, NULL);
#endif
}

void CondWait(COND *cond, MUTEX *mutex)
{
#ifdef __tds__
	MutexUnlock(mutex);
	int wakeup_flags;
	osal_flag_wait(&wakeup_flags, *cond, 1, OSAL_TWF_ORW | OSAL_TWF_CLR, OSAL_WAIT_FOREVER_TIME);
	MutexLock(mutex);
#else
	pthread_cond_wait(cond, mutex);
#endif
}

int CondWaitTimeout(COND *cond, MUTEX *mutex, int msec)
{
	int result = 0;
#ifdef __tds__
	MutexUnlock(mutex);
	int wakeup_flags;
	if (E_OK != osal_flag_wait(&wakeup_flags, *cond, 1, OSAL_TWF_ORW | OSAL_TWF_CLR, msec)) {
		result = -1;
	}
	MutexLock(mutex);
#else
	struct timespec ts;
	struct timeval tv;
	gettimeofday(&tv, NULL);
	ts.tv_sec = tv.tv_sec + msec / 1000;
	ts.tv_nsec = tv.tv_usec * 1000;
	/*
	  clock_gettime(CLOCK_REALTIME, &ts);
	  ts.tv_sec += msec / 1000;
	*/
	if (0 != pthread_cond_timedwait(cond, mutex, &ts)) {
		result = -1;
	}
#endif
	return result;
}

void CondNotify(COND *cond)
{
#ifdef __tds__
	osal_flag_set(*cond, 1);
#else
	pthread_cond_signal(cond);
#endif
}

void CondNotifyAll(COND *cond)
{
#ifdef __tds__
	// ~
#else
	pthread_cond_broadcast(cond);
#endif
}

void CondDestroy(COND *cond)
{
#ifdef __tds__
	osal_flag_delete(*cond);
#else
	pthread_cond_destroy(cond);
#endif
}

